#ifndef __BATMAN_H
#define __BATMAN_H

#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <string.h>
#include <queue>
#include <unistd.h>
#include <pthread.h>

#define NUM_DIRS 4

#define RIGHT_QUEUE(b) (b->dir()+1) % NUM_DIRS
#define LEFT_QUEUE(b)  (b->dir()-1) >= 0 ? (b->dir() - 1) : NUM_DIRS-1

enum direction {N=0, S=1, E=2, W=3};

class BAT;

class BATman {
private:
	std::queue<BAT*> Queue[NUM_DIRS];
	pthread_mutex_t Mutex[NUM_DIRS], // Synchronize unsafe C++ queues
		FWMutex, // First Waiting condition mutex
		CondMutex, // Used to synchronize the pthread cond
		crossing; // Protect access to the crossing
	pthread_cond_t Wait[NUM_DIRS]; // Enforce waiting in queues
	bool IsWaiting[NUM_DIRS],
		IsFirstWaiting[NUM_DIRS];

public:
	BATman();
	~BATman();

    void arrive(BAT *b);
    void cross(BAT *b);
    void leave(BAT *b);

    void check();
};

class BAT {
private:
    int m_num; // BAT's ID
    enum direction m_dir; // Direction the BAT's arriving from
	BATman *m_man;

public:
	BAT(int _num, enum direction _dir, BATman *_man);
	int num() {return m_num;}
    void num(int t) { this->m_num = t; }
	enum direction dir() {return m_dir;}
	void go();
};

#endif
